#!/usr/bin/python

import sys, re, os
from time import gmtime, strftime


def main():
    global currentuser
    if(not os.path.exists(sys.argv[1])):
        print 'The file you specified DNE.'
    else:
        cf = open(sys.argv[1], 'r')
        cmdstack = cf.readlines()
        cf.close()
        startup()
##special case for setup
    currentuser = User(' ')
    currentuser.is_admin = True
    for cmd in cmdstack[:4]:
        parse_cmdline(cmd.replace('\n','')) 
    currentuser = None
    groupdict['Administrators']=['admin']
##rest of input file      
    for cmd in cmdstack[4:]:
        parse_cmdline(cmd.replace('\n', ''))

def startup():
    global groupdict, acls, userlist
    #groupdict = {'Users':[], 'Administrators':[]}
    groupdict = {}
    acls = {}
    tmp = open('accounts.txt', 'w+')
    tmp.close()
    userlist = []
    if(os.path.exists('audit.txt')):
        tmp = open('audit.txt', 'w+')
        tmp.close()

def teardown():
    global groupdict, acls, userlist
    groupdict['Users']=userlist[1:]
    gf = open('groups.txt', 'w+')
    for g, m in groupdict.iteritems():
        gf.write(g+' '+' '.join(m)+'\n')
    #gf.write(' '.join(userlist)+'\n')
    gf.close()
    
    ff = open('files.txt', 'w+')
    for obj in acls.keys():
        ff.write('~'+obj+'~\nowner:'+acls[obj].owner+' F\n')
        ff.write('group access: \n')
        for gps in acls[obj].groups.keys():
            ff.write('\t'+gps+': '+''.join(acls[obj].groups[gps]).upper()+'\n')
        ff.write('User access: \n ')
        for u in acls[obj].users.keys():
            ff.write('\t'+u+': '+''.join(acls[obj].groups[u]).upper()+'\n')
            ##ff.write('\t- '+' '.join(groupdict[gps])+'\n')
        ff.write('\n')
    ff.close()
                     
def parse_cmdline(string):
    tokens = string.split()
    if(tokens[0] == 'login'):
        login(tokens[1], tokens[2])
    elif(currentuser):
        if(tokens[0] == 'logout'):
            logout()
        elif((tokens[0] == 'net')and(currentuser.is_admin==True)):
            if(tokens[1] == 'user'):
                createUser(tokens[2], tokens[3])
            elif(tokens[1] == 'group'):
                if(len(tokens)==3):
                    createGroup(tokens[2])
                elif(len(tokens)==4):
                    group_addUser(tokens[2], tokens[3])
        elif(tokens[0]=='create'):
            makeFile(tokens[1])
        elif(tokens[0]=='read'):
            catFile(tokens[1])
        elif(tokens[0]=='write'):
            scribbleFile(tokens[1], ' '.join(tokens[2:]))
        elif(tokens[0]=='execute'):
            executeFile(tokens[1])
        elif(tokens[0]=='xcacls'):
            editPerms(tokens[1], tokens[2:])
    elif(tokens[0]=='end'):
        teardown()
    else:
        print 'invalid command'

                    
def editPerms(filename, options):
    if((filename in acls) and (os.path.exists('accounts.txt'))):
        if((currentuser.uname == acls[filename].owner)or(currentuser.is_admin)):
            eflag = False
            if('/E' in options):
                editFlag = True
            elif('/G' in options):
                grantAccess(filename,options.pop(), eflag)
            elif('/P' in options):
                replaceAccess(filename,options.pop(), eflag)
            elif('/D' in options):
                denyAccess(filename, options.pop())
        else:
            audit(' user not permitted to change permissions')
    else:
        audit(' attempted to edit permissions to a file that DNE')

def grantAccess(filename, queso, eflag):
    subject = queso[0:queso.index(':')]
    perms = list(queso[queso.index(':')+1:].lower().replace('f', 'rwx'))
    
    if(subject in userlist):
        if(eflag):
            acls[filename].users[subject].append(perms)
        else:
            acls[filename].users[subject]=perms
        audit(' granted '+subject+' access to '+filename)
    elif(subject in groupdict.keys()):
        if(eflag):
            acls[filename].groups[subject].append(perms)
        else:
            acls[filename].groups[subject]=perms
        audit(' granted '+subject+' access to '+filename)
    else:
        audit(' attempted to grant '+subject+' access to '+filename)
    



def replaceAccess(filename, queso, eflag):
    acls[filename][subject]=perms

def denyAccess(filename, queso):
    global acls
    subject = queso
    if(subject in userlist):
        acls[filename].users[subject]=perms
        audit(' denied '+subject+' access to '+filename)
    elif(subject in groupdict.keys()):
        acls[filename].groups[subject]=perms
        audit(' denied '+subject+' access to '+filename)
    else:
        audit(' attempted to deny '+subject+' access to '+filename+' without permission')


def login(uname, passwd):
    global currentuser, groupdict
    tmpf = open('accounts.txt', 'r')
    for l in tmpf.readlines():
        u = l[:l.index(' ')]
        p = l[l.index(' ')+1:].replace('\n', '')
        if((uname==u)and(passwd==p)):
            currentuser = User(uname)
            if((currentuser.uname in groupdict['Administrators'])or(uname=='admin')):
                currentuser.is_admin = True
            audit(' logged in')
            tmpf.close()
            return True
    
    tmpf.close()


def logout():
    global currentuser
    audit(' logged out')
    currentuser = None

##create file command
def makeFile(filename):
    global acls
    if(filename not in acls):
        tmpF = open(filename, 'w+')
        tmpF.close()
        audit(' created '+filename)
        acls[filename] = ACL(filename, currentuser.uname) ##create default acl for file
        acls[filename].groups['Administrators']=['r','w','x']
        if(currentuser.is_admin):
            acls[filename].groups['Users']=['r']
        


def catFile(filename):
    global currentuser, acls
    if(filename not in acls):
        audit(' attempted to view file that DNE')
    elif(acls[filename].has_permission(currentuser.uname, 'r')):
        tmpf = open(filename,'r')
        audit(' read '+filename+' as: '+tmpf.read())
    else:
        audit(' attempted to read '+filename+' without permission')

def scribbleFile(filename, text):
    global currentuser, acls
    if(filename in acls):
        if(acls[filename].has_permission(currentuser.uname, 'w')):
            tmpf = open(filename, 'a')
            tmpf.write(text+'\n')
            tmpf.close()
            audit(' wrote to '+filename)
        else: 
            audit(' attempted to write to '+filename+' without permission')
    else:
        audit(currentuser+' attempted to write to a file '+filename+' that DNE.')


def executeFile(filename):
    global acls, currentuser
    if(filename in acls):
        if(acls[filename].has_permission(currentuser.uname, 'x')):
            audit(' executed '+filename+' successfully.')
        else:
            audit(' attempted to execute '+filename+'. Permission denied')
    else:
        audit(' execute failed. '+filename+' DNE')

##su commands
def createGroup(gname):
    global groupdict, currentuser
    if(gname in groupdict):
        audit(' failed to create group. '+gname+' name in use')
    else:
        groupdict[gname] = []
	audit(' created group '+gname)
       
def group_addUser(gname, uname):
    global groupdict, currentuser
    if(gname in groupdict):
        if(uname not in groupdict[gname]):
            groupdict[gname].append(uname)
            audit(' added '+uname+' to group '+gname)
        else:
	 	audit( uname+' is already member of '+gname)
    else: 
	audit('You must first create the group before populating it.')

def createUser(uname, passwd):
    global groupdict, currentuser, userlist
    tmpf = open('accounts.txt','r')
    if(uname in tmpf.read()):
        tmpf.close()
    else:
        tmpf.close()
        tmpf = open('accounts.txt', 'a')
        tmpf.write(uname+' '+passwd+'\n')
        tmpf.close()
        userlist.append(uname)
	audit(' created user '+uname)

##end su commands

def audit(stuff):
    auditFile = open('audit.txt', 'a')
    auditFile.write(timestamp()+'\t'+currentuser.uname+stuff+'\n')
    print currentuser.uname+stuff

def timestamp():
        return strftime("%Y-%m-%d %H:%M:%S", gmtime())
	

class User:
    def __init__(self, u):
        self.is_admin = False
        self.uname = u


class ACL:
    def __init__(self, fname, owner):
        self. filename = fname
        self.owner = owner
        self.users = {}
        self.groups = {}

    def has_permission(self, user, perm):
        global groupdict
        if((user in self.users)and(perm in self.users[user])):
            return True
        if(self.owner == user):
            return True
        for g in self.groups.keys():
            if((user in groupdict[g]) and (perm in self.groups[g])):
                return True
        return False

if __name__ == '__main__':
    main()
